package cn.ywyself.extend.directive;

import cn.ywyself.extend.utils.EscapeUtils;
import com.jfinal.template.Directive;
import com.jfinal.template.Env;
import com.jfinal.template.TemplateException;
import com.jfinal.template.expr.ast.Expr;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.io.Writer;
import com.jfinal.template.stat.ParseException;
import com.jfinal.template.stat.Scope;

/**
 * HTML转义，JavaScript字符转义<br>
 * 使用：<br>
 * <li>参数1：需要转义的字符串</li>
 * <li>参数2：转义方式，缺省值为'html'</li>
 *
 * @author : ywyself
 * @created : 2018-10-10 11:29
 */
public class EscapeUtilsDirective extends Directive {

    private int paraNum;
    private Expr textExpr;
    private Expr typeExpr;

    @Override
    public void setExprList(ExprList exprList) {
        this.paraNum = exprList.length();
        if (this.paraNum == 0) {
            throw new ParseException("Wrong number parameter of # directive, one parameters allowed at least", location);
        } else if (this.paraNum == 1) {
            this.typeExpr = null;
            this.textExpr = exprList.getFirstExpr();
        } else if (this.paraNum == 2) {
            this.textExpr = exprList.getFirstExpr();
            this.typeExpr = exprList.getExpr(1);
        } else {
            throw new ParseException("Wrong number parameter of # directive, two parameters allowed at most", location);
        }
    }

    @Override
    public void exec(Env env, Scope scope, Writer writer) {
        Object value = textExpr.eval(scope);
        if (value == null) {
            value = "";
        } else if (!(value instanceof String)) {
            throw new TemplateException("The first parameter pattern of # directive must be String", location);
        }
        // 只有一个参数，需要转义的字符串
        if (this.paraNum == 1) {
            output(writer, (String) value);
        }
        // 有两个参数，需要转义的字符串，转义方式
        else if (this.paraNum == 2) {
            Object type = typeExpr.eval(scope);
            if (type == null) {
                type = "html";
            } else if (!(type instanceof String)) {
                throw new TemplateException("The second parameter pattern of # directive must be String", location);
            }
            output(writer, (String) value, (String) type);
        }
    }

    private void output(Writer writer, String text) {
        output(writer, text, "html");
    }

    private void output(Writer writer, String text, String type) {
        if (type == null) {
            type = "html";
        }
        switch (type.toLowerCase()) {
            case "javascript":
            case "js":
                text = EscapeUtils.escapeJavaScript(text);
                break;
            default:
                text = EscapeUtils.escapeHtml(text);
        }
        write(writer, text);
    }
}
